package ufpi.br.dao;

import br.ufpi.domain.Pergunta;
import br.ufpi.domain.Resposta;
import br.ufpi.domain.Usuario;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Collection;
import java.util.Date;
import org.hibernate.Criteria;
import org.hibernate.criterion.Criterion;
import org.hibernate.criterion.LogicalExpression;
import org.hibernate.criterion.Order;
import org.hibernate.criterion.Projections;
import org.hibernate.criterion.Restrictions;

public class RespostaDao extends DAOImpl<Resposta> {

    public RespostaDao() {
        super(Resposta.class);
    }

    @Override
    protected Long getIdObj(Resposta obj) {
        return obj.getId();
    }

    @Override
    protected void setIdObj(Resposta obj, Long id) {
        obj.setId(id);
    }

    public Collection<Resposta> getRespostas(Long idPergunta, String matricula) {
        UsuarioDao usuarioDao = new UsuarioDao();
        Usuario usuario = usuarioDao.buscaMatricula(matricula);
        PerguntaDao perguntaDao = new PerguntaDao();
        Pergunta pergunta = perguntaDao.findByID(idPergunta);
        Criteria criteria = getSession().createCriteria(Resposta.class);
        LogicalExpression and = Restrictions.and(Restrictions.eq("pergunta", pergunta), Restrictions.eq("status", 2));
        criteria.add(Restrictions.or(and, Restrictions.and(Restrictions.eq("usuario", usuario), Restrictions.eq("pergunta", pergunta))));
        //TODO Adicionar uma restrição para ordernar perguntas
        return (Collection<Resposta>) criteria.list();
    }

    /**
    Date igual a null se for todas as respostas sem uma data especifica*/
    public Collection getRespostasPontuadas(String matricula, Date date, Date finalDate) {
        UsuarioDao usuarioDao = new UsuarioDao();
        ArrayList arrayList = new ArrayList();
        Usuario usuario = usuarioDao.buscaMatricula(matricula);
        Criteria pontuacaoTotal = getSession().createCriteria(Resposta.class);
        Criteria criteria = getSession().createCriteria(Resposta.class);
        Criterion not = Restrictions.not(Restrictions.eq("pontuacao", 0.0));
        LogicalExpression expression = Restrictions.and(not, Restrictions.eq("usuario", usuario));
        if (date != null) {
            if (finalDate != null) {
                expression = Restrictions.and(expression, Restrictions.between("dataEnvio", date, finalDate));
            } else {
                expression = Restrictions.and(expression, Restrictions.between("dataEnvio", date, new Date()));
            }
        } else {
            if (finalDate != null) {
                Date aux = new Date();
                Calendar calendar = Calendar.getInstance();
                calendar.set(2000, 0, 0);
                aux = calendar.getTime();
                expression = Restrictions.and(expression, Restrictions.between("dataEnvio", aux, finalDate));
            }
        }
        criteria.add(expression);
        pontuacaoTotal.add(expression);
        arrayList.add(pontuacaoTotal.setProjection(Projections.sum("pontuacao")).uniqueResult());
        criteria.addOrder(Order.desc("id"));
        arrayList.add(criteria.list());
        return arrayList;
    }

    public Collection<Resposta> listByStatusAndUsuario(String matricula, int status) {
        Criteria criteria = getSession().createCriteria(Resposta.class);
        UsuarioDao usuarioDao = new UsuarioDao();
        Usuario usuario = usuarioDao.buscaMatricula(matricula);
        criteria.add(Restrictions.and(Restrictions.eq("status", status), Restrictions.eq("usuario", usuario)));
        criteria.addOrder(Order.desc("id"));
        return criteria.list();
    }

    public Collection<Resposta> listMaiorPontuacao(int listaMaxima, Date date, Date finalDate) {
        Criteria criteria = getSession().createCriteria(Resposta.class);
        Criterion expression = null;
        if (date != null) {
            if (finalDate != null) {
                expression = Restrictions.between("dataEnvio", date, finalDate);
            } else {
                expression = Restrictions.between("dataEnvio", date, new Date());
            }
        } else {
            if (finalDate != null) {
                Date aux = new Date();
                Calendar calendar = Calendar.getInstance();
                calendar.set(2000, 0, 0);
                aux = calendar.getTime();
                expression = Restrictions.between("dataEnvio", aux, finalDate);
            }
        }

        criteria.setMaxResults(listaMaxima);
        if (expression != null) {
            criteria.add(expression);
        }
        criteria.addOrder(Order.desc("pontuacao"));
        return criteria.list();
    }
/**
 * Lista as respostas de uma pergunta por status
 * @param idPergunta
 * @param status
 * @return
 */
    public Collection<Resposta> listByStatusFromPergunta(Long idPergunta, int status) {
        Criteria criteria = getSession().createCriteria(Resposta.class);
        criteria.add(Restrictions.eq("status", status));
        criteria.addOrder(Order.desc("id"));
        return criteria.list();
    }
/**
 * Lista todas as respostas de uma pergunta
 * @param idPergunta
 * @return
 */
    public Collection<Resposta> listAllFromPergunta(Long idPergunta) {
        Criteria criteria = getSession().createCriteria(Resposta.class);
        PerguntaDao dao = new PerguntaDao();
        Pergunta p = dao.findByID(idPergunta);
        criteria.add(Restrictions.eq("pergunta", p));
        criteria.addOrder(Order.desc("id"));
        return criteria.list();
    }
}
